Conversation
|
Warning Rate limit exceeded
⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. 📒 Files selected for processing (6)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
| Filename | Overview |
|---|---|
| migrations/004_role_menu_templates.cjs | Adds role_menu_templates table with appropriate indexes for built-in and guild-specific templates |
| src/modules/roleMenuTemplates.js | Implements core template management logic with proper validation, parameterized queries, and Winston logging |
| src/commands/rolemenu.js | Implements /rolemenu command with template operations; has logic issue with shouldEnable flag when merging built-in templates |
| src/index.js | Adds seedBuiltinTemplates call during startup with proper error handling |
Sequence Diagram
sequenceDiagram
participant User
participant Discord
participant rolemenu.js
participant roleMenuTemplates.js
participant Database
participant config.js
User->>Discord: /rolemenu template apply <name> [merge]
Discord->>rolemenu.js: handleApply()
rolemenu.js->>roleMenuTemplates.js: getTemplateByName(guildId, name)
roleMenuTemplates.js->>Database: SELECT template WHERE visible to guild
Database-->>roleMenuTemplates.js: template row
roleMenuTemplates.js-->>rolemenu.js: template object
rolemenu.js->>config.js: getConfig(guildId)
config.js-->>rolemenu.js: existing roleMenu config
rolemenu.js->>roleMenuTemplates.js: applyTemplateToOptions(tpl, existing)
Note over roleMenuTemplates.js: Merge template options<br/>with existing roleIds<br/>by label matching
roleMenuTemplates.js-->>rolemenu.js: merged options
Note over rolemenu.js: Filter out options<br/>with empty roleIds
rolemenu.js->>config.js: setConfigValue('welcome.roleMenu.enabled', shouldEnable)
rolemenu.js->>config.js: setConfigValue('welcome.roleMenu.options', validOptions)
config.js->>Database: UPDATE guild_configs
rolemenu.js->>Discord: Reply with success message
Discord->>User: Template applied confirmation
Last reviewed commit: 2e3d6ce
Fixes three performance bottlenecks identified in code review of recently merged features (PR #121 conversations viewer, PR #190 AI feedback). ## Changes ### migrations/004_performance_indexes.cjs (new) Four new indexes targeting hot query paths: - idx_ai_feedback_guild_created (guild_id, created_at DESC) getFeedbackTrend() and getRecentFeedback() filtered by guild_id AND created_at but only had a single-column guild_id index, forcing a full guild scan + sort on every trend/recent call. - idx_conversations_content_trgm (GIN, pg_trgm) content ILIKE '%...%' search was a sequential scan. GIN/trgm index reduces this from O(n) to O(log n * trigram matches). Requires pg_trgm extension (added idempotently). - idx_conversations_guild_created (guild_id, created_at DESC) Default 30-day listing query filters guild_id + created_at. The existing 3-column (guild_id, channel_id, created_at) composite is suboptimal when channel_id is not in the predicate. - idx_flagged_messages_guild_message (guild_id, message_id) Conversation detail + flag endpoints query flagged_messages by guild_id AND message_id = ANY(...). Existing index only covers (guild_id, status). ### src/api/routes/conversations.js **GET / — Replace in-memory pagination with SQL CTE grouping** Before: fetched up to 10,000 message rows into Node memory, grouped them in JavaScript (O(n) time + memory), then sliced for pagination. Every page request loaded the full 10k row dataset. After: single SQL query using window functions (LAG + SUM OVER) to identify conversation boundaries and aggregate summaries directly. COUNT(*) OVER() provides total count without a second query. Pagination happens at the DB with LIMIT/OFFSET on summary rows. Memory overhead is now proportional to page size (default 25), not total conversation volume. Removed now-unused buildConversationSummary() helper (logic inlined into the SQL-side aggregation). **POST /:conversationId/flag — Parallel verification queries** Before: msgCheck and anchorCheck ran sequentially (~2× RTT). After: both run in parallel via Promise.all (1× RTT for verification). ### tests/api/routes/conversations.test.js Updated 'should return paginated conversations' test to mock the new SQL CTE response shape (pre-aggregated summary rows) instead of raw message rows. All 41 conversation tests pass.
* feat: quiet mode per-channel via bot mention (#173) - Add quietMode.js module with Redis+memory storage - Parse duration from natural language (30m, 1 hour, etc.) - Permission gated via config.quietMode.allowedRoles - Commands: quiet, unquiet, status - Suppress AI responses during quiet mode in events.js - Add quietMode section to config.json (disabled by default) - Add quietMode to configAllowlist.js for dashboard editing * test: add quiet mode tests (41 tests, all passing) * style: fix biome formatting in quietMode.js, events.js, and test * fix(web): fix ai-feedback-stats TypeScript and formatting errors * fix: gate quiet mode checks on enabled flag, validate TTL, honor maxDurationMinutes config - events.js: Wrap isQuietMode() calls in guildConfig.quietMode?.enabled check to avoid unnecessary Redis lookups and prevent stale records from suppressing AI responses when the feature is disabled (PRRT_kwDORICdSM5xdbmp, PRRT_kwDORICdSM5xdbmx) - quietMode.js: Add TTL validation in setQuiet() to guard against 0, negative, or NaN values that would error in Redis (PRRT_kwDORICdSM5xdbm3) - quietMode.js: Update parseDurationFromContent() to accept config parameter and honor guildConfig.quietMode.maxDurationMinutes. Also clamp defaultSeconds to the effective max (PRRT_kwDORICdSM5xdbm_) - configValidation.js: Add quietMode schema entry with enabled, maxDurationMinutes, and allowedRoles properties (PRRT_kwDORICdSM5xdbnH) * style: fix biome formatting in quietMode.js and ai-feedback-stats.tsx
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 16 out of 16 changed files in this pull request and generated 8 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 6 out of 6 changed files in this pull request and generated 5 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Add ORDER BY to getTemplateByName for deterministic results - Fix roleId precedence to preserve existing roleIds during merge - Truncate Discord embed field values to 1024 chars
The test expected template roleId to win, but the comment said existing should take precedence. Fixed assertion to match documented behavior.
- Filter out options with empty roleIds before saving - Only enable role menu for non-built-in templates with valid options - Add user-facing note when options are filtered
Use LOWER(name) in unique index to match case-insensitive queries and prevent duplicate templates differing only by case.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 6 out of 6 changed files in this pull request and generated 9 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- validateTemplateOptions now validates that optional roleId and description fields are strings when present - Update JSDoc @see reference from issue #135 (voice tracking) to issue #216 (role menu templates) - Update ON CONFLICT clause to use constraint name for consistency with the new LOWER(name) index
Summary
Implements reusable role menu templates as described in #135.
Features
Pre-defined built-in templates (auto-seeded on startup)
Custom template creation
/rolemenu template create <name> <options-json>— create a guild-specific templatelabel,description, androleIdfieldsOne-click apply
/rolemenu template apply <name> [merge]— applies template to guild'swelcome.roleMenuconfigmergeflag preserves existing options (role IDs carried over by label matching)Template sharing between guilds
/rolemenu template share <name> <true|false>— toggle cross-guild visibilityAdditional commands
/rolemenu template list— categorised embed of all visible templates/rolemenu template info <name>— details + option list/rolemenu template delete <name>— delete owned templateDatabase
Migration
004_role_menu_templates.cjsaddsrole_menu_templatestable with:(name, guild_id)(built-ins keyed to__builtin__sentinel)Tests
roleMenuTemplates.test.js)rolemenu.test.js)Closes #135